#ifndef MODBUS_H_
#define MODBUS_H_

#include <stdint.h>
#include "main.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_gpio_ex.h"
#include "stm32f4xx_hal_usart.h"

#define MODBUS_SIZE_BUF_TX	30
#define MODBUS_SIZE_BUF_RX	50

#define MODBUS_MINIMAL_CORECT_PACKET	4

enum E_MODBUS_LINES
{
	E_MODBUS_ALL_LINES		= 4,
	E_MODBUS_MAX_DEV_LINE 	= 64
};

enum E_MODBUS_CHANNELS
{
	E_MODBUS_CHANNEL_0,
	E_MODBUS_CHANNEL_1,
	E_MODBUS_CHANNEL_2,
	E_MODBUS_CHANNEL_3
};

/*
 * Baudrate constants
 */
enum 	eModbusBaudrate { E_MODBUS_BAUD2400,	E_MODBUS_BAUD4800,	E_MODBUS_BAUD9600,	E_MODBUS_BAUD19200};
#define	BAUD2400	(uint16_t) 2400
#define BAUD4800	(uint16_t) 4800
#define BAUD9600	(uint16_t) 9600
#define BAUD19200	(uint16_t) 19200

#define E_MODBUS_DIRECT_NON				0
#define E_MODBUS_DIRECT_TX				1
#define E_MODBUS_DIRECT_RX				2

enum E_MODBUS_CRC
{
	E_MODBUS_CRC_OK 	= 				0x55,
	E_MODBUS_CRC_ERROR = 				0x00
};

enum E_MODBUS_PROTOCOL
{
	E_MODBUS_PROTOCOL_STANDARD 		= 0x00,
	E_MODBUS_PROTOCOL_NOT_STANDARD 	= 0x01
};

#define MODBUS_MAX_SIZE_PACK	64
typedef struct sModbusReq
{
	uint8_t state;
	uint8_t channel;
	uint8_t baudrate;
	uint8_t counter;
	uint8_t tx_buf[MODBUS_MAX_SIZE_PACK];
	uint8_t txLeng;
	uint8_t txCounter;
	uint8_t rx_buf[MODBUS_MAX_SIZE_PACK];
	uint8_t rxLeng;
	uint8_t crc_state;
}sModbusReq;

extern sModbusReq modbusReq;

enum E_Modbus_State
{
	E_MODBUS_STATE_IDLE 				= 0x00,
	E_MODBUS_STATE_START_ALARM			= 0x01,
	E_MODBUS_STATE_START_MANUAL			= 0x02,
	E_MODBUS_STATE_TX	 				= 0x04,
	E_MODBUS_STATE_RX	 				= 0x08,
	E_MODBUS_STATE_TX_COMPLETE			= 0x10,
	E_MODBUS_STATE_RX_BUSY				= 0x20
};

/*
 * Functions
 */
void ModbusInit(void);
void ModbusTask(void *pvParameters);
uint16_t getCRC(uint8_t*data_value, uint16_t data_length);
void ModbusRawHandler(void);

/*
 * Peripheral Defines
 */

#define MODBUS_USART					USART6
#define MODBUS_USARTx_CLK_ENABLE()      __HAL_RCC_USART6_CLK_ENABLE()
#define MODBUS_DMAx_CLK_ENABLE()		__HAL_RCC_DMA2_CLK_ENABLE()

#define MODBUS_USART_FORCE_RESET()      __HAL_RCC_USART6_FORCE_RESET()
#define MODBUS_USART_RELEASE_RESET()    __HAL_RCC_USART6_RELEASE_RESET()

#define MODBUS_USART_DMA_TX_IRQn        DMA2_Stream6_IRQn
#define MODBUS_USART_DMA_RX_IRQn        DMA2_Stream1_IRQn
#define MODBUS_USART_DMA_TX_IRQHandler  DMA2_Stream6_IRQHandler
#define MODBUS_USART_DMA_RX_IRQHandler  DMA2_Stream1_IRQHandler
#define MODBUS_USART_IRQn               USART6_IRQn
#define MODBUS_USART_IRQHandler         USART6_IRQHandler

#define MODBUS_USART_TX_DMA_CHANNEL     DMA_CHANNEL_4
#define MODBUS_USART_TX_DMA_STREAM      DMA2_Stream6
#define MODBUS_USART_RX_DMA_CHANNEL     DMA_CHANNEL_4
#define MODBUS_USART_RX_DMA_STREAM      DMA2_Stream1

#define USART_DMA_STREAM_TX_INTERRUPT	DMA2_Stream6_IRQn

#define USART_DMA_STREAM_COMPLETE_TX	DMA_IT_TCIF6
#define USART_DMA_STREAM_COMPLETE_RX	DMA_IT_TCIF6

#define	MODBUS_TIMER_ENABLE				__HAL_RCC_TIM4_CLK_ENABLE()
#define	MODBUS_TIMER_IRQn				TIM4_IRQn
#define MODBUS_TIMER_IRQHandler			TIM4_IRQHandler
#define MODBUS_TIMER					TIM4
#define MODBUS_TIMER_CH					CH1

#define MODBUS_GPIO_RCC_AHB				AHB1ENR
#define MODBUS_GPIO_RCC_EN				( RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIODEN )

#define MODBUS_RX_PIN					GPIO_PIN_7
#define MODBUS_RX_PORT					GPIOC
#define MODBUS_RX_AF					GPIO_AF8_USART6

#define MODBUS_TX_PIN					GPIO_PIN_6
#define MODBUS_TX_PORT					GPIOC
#define MODBUS_TX_AF					GPIO_AF8_USART6

#define MODBUS_RAW_OUT_RX_PIN			GPIO_PIN_8
#define MODBUS_RAW_OUT_RX_PORT			GPIOC

#define MODBUS_RAW_IN_TX_PIN			GPIO_PIN_9
#define MODBUS_RAW_IN_TX_PORT			GPIOC

#define MODBUS_RX_RAW_SET_1				MODBUS_RAW_OUT_RX_PORT->ODR |= MODBUS_RAW_OUT_RX_PIN
#define MODBUS_RX_RAW_SET_0				MODBUS_RAW_OUT_RX_PORT->ODR &=~ MODBUS_RAW_OUT_RX_PIN

#define MODBUS_CHANNEL0_TX_PIN			GPIO_PIN_8
#define MODBUS_CHANNEL0_TX_PORT			GPIOB
#define MODBUS_CHANNEL0_RX_PIN			GPIO_PIN_4
#define MODBUS_CHANNEL0_RX_PORT			GPIOB
#define MODBUS_CHANNEL0_RE_PIN			GPIO_PIN_7
#define MODBUS_CHANNEL0_RE_PORT			GPIOB

#define MODBUS_CHANNEL1_TX_PIN			GPIO_PIN_3
#define MODBUS_CHANNEL1_TX_PORT			GPIOB
#define MODBUS_CHANNEL1_RX_PIN			GPIO_PIN_13
#define MODBUS_CHANNEL1_RX_PORT			GPIOG
#define MODBUS_CHANNEL1_RE_PIN			GPIO_PIN_14
#define MODBUS_CHANNEL1_RE_PORT			GPIOG

#define MODBUS_CHANNEL2_TX_PIN			GPIO_PIN_12
#define MODBUS_CHANNEL2_TX_PORT			GPIOG
#define MODBUS_CHANNEL2_RX_PIN			GPIO_PIN_10
#define MODBUS_CHANNEL2_RX_PORT			GPIOG
#define MODBUS_CHANNEL2_RE_PIN			GPIO_PIN_11
#define MODBUS_CHANNEL2_RE_PORT			GPIOG

#define MODBUS_CHANNEL3_TX_PIN			GPIO_PIN_9
#define MODBUS_CHANNEL3_TX_PORT			GPIOG
#define MODBUS_CHANNEL3_RX_PIN			GPIO_PIN_4
#define MODBUS_CHANNEL3_RX_PORT			GPIOD
#define MODBUS_CHANNEL3_RE_PIN			GPIO_PIN_7
#define MODBUS_CHANNEL3_RE_PORT			GPIOD

#endif
